﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ProtocolManagerViewModel.cs" company="R.V.Kasner">
//   Copyright © 2011 R.V.Kasner
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace Owen.Terminal.ViewModel
{
    using System;
    using System.Collections.Generic;

    using Microsoft.Practices.Prism.Events;

    using Owen.Communication.Protocols;
    using Owen.Communication.Service;
    using Owen.Terminal.Commons;
    using Owen.Terminal.Events;
    using Owen.Terminal.View;

    public sealed class ProtocolManagerViewModel : ViewModelBase<IProtocolManagerView>, IProtocolManagerViewModel, IProtocolManager
    {
        private readonly IEventAggregator aggregator;

        private readonly IEnumerable<IProtocol> protocols;

        private int deviceAddress;

        private bool is11Bit;

        private IProtocol protocol;

        private ProtocolSettings settings;

        private int delayPackage;

        private int delayCicles;

        public ProtocolManagerViewModel()
        {
            this.deviceAddress = 1;
            this.delayPackage = 150;
            this.delayCicles = 300;
            this.protocol = Chef.ModBusRtu;
            this.protocols = new IProtocol[] { Chef.ModBusRtu, Chef.ModBusAscii, Chef.OwenBus, };
        }

        public ProtocolManagerViewModel(IProtocolManagerView view, IEventAggregator aggregator)
            : base(view)
        {
            this.aggregator = aggregator;

            var defProtName = Properties.Settings.Default.Protocol;
            if (defProtName == Chef.ModBusRtu.Name) this.protocol = Chef.ModBusRtu;
            else if (defProtName == Chef.ModBusAscii.Name) this.protocol = Chef.ModBusAscii;
            else if (defProtName == Chef.OwenBus.Name) this.protocol = Chef.OwenBus;
            else Properties.Settings.Default.Protocol = (this.protocol = Chef.ModBusRtu).Name;

            this.deviceAddress = Properties.Settings.Default.Address;
            this.is11Bit = Properties.Settings.Default.Owen11BitAddress;
            this.delayPackage = Properties.Settings.Default.DelayPackage;
            this.delayCicles = Properties.Settings.Default.DelayCicles;

            this.settings = new ProtocolSettings(
                this.deviceAddress, this.protocol, this.is11Bit,
                this.delayCicles, this.delayPackage);

            this.IsEditable = true;

            this.protocols = new IProtocol[] { Chef.ModBusRtu, Chef.ModBusAscii, Chef.OwenBus, };

            this.aggregator.GetEvent<ConnectChangeEvent>().Subscribe(
                cs =>
                    {
                        this.IsEditable = (cs & SignallerStates.Transmit) != SignallerStates.Transmit;
                        this.RaisePropertyChanged("IsEditable");
                    });
        }

        public event Action<ProtocolSettings> SettingsChange;

        public ProtocolSettings Settings
        {
            get
            {
                return this.settings;
            }
        }

        public int DeviceAddress
        {
            get
            {
                return this.deviceAddress;
            }

            set
            {
                this.deviceAddress = value;
                this.RaisePropertyChanged("DeviceAddress");
                this.RaiseProtocolChange();
            }
        }

        public bool Is11Bit
        {
            get
            {
                return this.is11Bit;
            }

            set
            {
                this.is11Bit = value;
                this.RaisePropertyChanged("Is11Bit");
                this.RaiseProtocolChange();
            }
        }

        public bool IsEditable { get; private set; }

        public int DelayPackage
        {
            get
            {
                return this.delayPackage;
            }

            set
            {
                this.delayPackage = value;
                this.RaisePropertyChanged("DelayPackage");
                this.RaiseProtocolChange();
            }
        }

        public int DelayCicles
        {
            get
            {
                return this.delayCicles;
            }

            set
            {
                this.delayCicles = value;
                this.RaisePropertyChanged("DelayCicles");
                this.RaiseProtocolChange();
            }
        }

        public IEnumerable<IProtocol> Protocols
        {
            get
            {
                return this.protocols;
            }
        }

        public IProtocol SelectedProtocol
        {
            get
            {
                return this.protocol;
            }

            set
            {
                if (this.protocol == value) return;
                this.protocol = value;
                this.RaisePropertyChanged("SelectedProtocol");
                this.RaiseProtocolChange();
            }
        }

        private void RaiseProtocolChange()
        {
            Properties.Settings.Default.Protocol = this.protocol.Name;
            Properties.Settings.Default.Address = this.deviceAddress;
            Properties.Settings.Default.Owen11BitAddress = this.is11Bit;
            Properties.Settings.Default.DelayCicles = this.delayCicles;
            Properties.Settings.Default.DelayPackage = this.delayPackage;

            this.settings = new ProtocolSettings(
                this.deviceAddress, this.protocol, this.is11Bit,
                this.delayCicles, this.delayPackage);
            var handler = this.SettingsChange;
            if (handler != null) handler(this.settings);
        }
    }
}